package com.travel.server.manager.impl.command.customer.data;

import com.travel.common.util.CollectionUtil;
import com.travel.common.util.DateUtil;
import com.travel.server.manager.dto.request.customer.data.QueryCustomerDataRequest;
import com.travel.server.manager.dto.response.customer.data.QueryCustomerDataResponse;
import com.travel.server.manager.dto.response.customer.data.QueryCustomerDataResponse.CustomerDataItem;
import com.travel.server.manager.impl.command.AbstractCommand;
import com.travel.server.manager.impl.dal.CustomerDal;
import com.travel.server.manager.impl.dal.OrderDal;
import com.travel.server.manager.impl.dal.data.CustomerDataDal;
import com.travel.server.manager.impl.sal.OrderDataSal;
import com.travel.server.manager.impl.vo.DataDateVo;
import com.travel.server.manager.model.MemberGradeInfo;
import com.travel.server.manager.model.dto.data.CustomerDataDto;
import com.travel.server.manager.model.dto.data.OrderDataDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @Author: LiZhenhui
 * @Date: 2018/12/10 10:18
 * @Desc:
 */
@Component
@Slf4j
public class QueryCustomerDataCommand extends AbstractCommand<QueryCustomerDataRequest, QueryCustomerDataResponse> {

    @Autowired
    private OrderDal orderDal;

    @Autowired
    private CustomerDal customerDal;

    @Autowired
    private CustomerDataDal customerDataDal;

    @Override
    protected void checkInput(QueryCustomerDataRequest request) {
        checkTimeInput(request);
        if(request.getType() == null){
            throwInvalidParam();
        }
    }

    @Override
    public QueryCustomerDataResponse handle(QueryCustomerDataRequest request) {
        checkInput(request);

        MemberGradeInfo member = customerDataDal.getMember();
        MemberGradeInfo highMember = customerDataDal.getHighMember();

        DataDateVo dateVo = OrderDataSal.getDate(request.getType(), request);
        Date startTime = dateVo.getStartTime();
        Date endTime = dateVo.getEndTime();

        List<CustomerDataDto> customerDataList = customerDal.selectCustomerData(null, endTime, member.getId(), highMember.getId());
        List<OrderDataDto> orderDataList = orderDal.selectOrderData(null, endTime);
        return makeResponse(startTime, endTime, customerDataList, orderDataList);
    }

    private QueryCustomerDataResponse makeResponse(Date startTime, Date endTime, List<CustomerDataDto> customerDataList, List<OrderDataDto> orderDataList){
        QueryCustomerDataResponse response = new QueryCustomerDataResponse();
        int currentCustomer = 0;
        int lastCustomer = 0;
        if(!CollectionUtil.isEmpty(orderDataList)){
            for(OrderDataDto dataDto : orderDataList){
                Date date = DateUtil.getDataTime(dataDto.getDays());
                if(date.before(startTime)){
                    lastCustomer += dataDto.getPayNum();
                }
                currentCustomer += dataDto.getPayNum();
            }
        }
        int currentMember = 0;
        int lastMember = 0;
        int currentHighMember = 0;
        int lastHighMember = 0;
        int currentNotMember = 0;
        int lastNotMember = 0;
        if(!CollectionUtil.isEmpty(customerDataList)){
            for(CustomerDataDto dataDto : customerDataList){
                Date date = DateUtil.getDataTime(dataDto.getDays());
                if(date.before(startTime)){
                    lastMember += dataDto.getMember();
                    lastHighMember += dataDto.getHighMember();
                    lastNotMember += dataDto.getNotMember();
                }
                currentMember += dataDto.getMember();
                currentHighMember += dataDto.getHighMember();
                currentNotMember += dataDto.getNotMember();

            }
        }
        response.setCustomer(currentCustomer);
        response.setCustomerCompare(OrderDataSal.getProportion(currentCustomer, lastCustomer));
        response.setMember(currentMember);
        response.setMemberCompare(OrderDataSal.getProportion(currentMember, lastMember));
        response.setHighMember(currentHighMember);
        response.setHighMemberCompare(OrderDataSal.getProportion(currentHighMember, lastHighMember));
        response.setNotMember(currentNotMember);
        response.setNotMemberCompare(OrderDataSal.getProportion(currentNotMember, lastNotMember));
        response.setVisit(0);
        response.setVisitCompare("0%");
        response.setCustomerDataList(makeCustomerDataList(startTime, endTime, customerDataList, orderDataList));
        return response;
    }

    private List<CustomerDataItem> makeCustomerDataList(Date startTime, Date endTime, List<CustomerDataDto> customerDataList, List<OrderDataDto> orderDataList){
        Map<String, Integer> customerMap = makeCustomerDataMap(customerDataList);
        Map<String, Integer> orderMap = makeOrderDataMap(orderDataList);
        List<CustomerDataItem> list = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);
        while(calendar.getTime().before(endTime) || calendar.getTime().equals(endTime)){
            String key = DateUtil.YYYY_MM_DD.format(calendar.getTime());
            Integer member = customerMap.get(key);
            Integer customer = orderMap.get(key);
            CustomerDataItem item = new CustomerDataItem();
            item.setDate(calendar.getTime());
            item.setVisit(0);
            item.setCustomer(customer == null ? 0 : customer);
            item.setMember(member == null ? 0 : member);
            list.add(item);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
        }
        return list;
    }

    private Map<String, Integer> makeCustomerDataMap(List<CustomerDataDto> customerDataList){
        Map<String, Integer> map = new HashMap<>();
        if(!CollectionUtil.isEmpty(customerDataList)){
            for(CustomerDataDto dto : customerDataList){
                map.put(dto.getDays(), dto.getMember());
            }
        }
        return map;
    }

    private Map<String, Integer> makeOrderDataMap(List<OrderDataDto> orderDataList){
        Map<String, Integer> map = new HashMap<>();
        if(!CollectionUtil.isEmpty(orderDataList)){
            for(OrderDataDto dto : orderDataList){
                map.put(dto.getDays(), dto.getPayNum());
            }
        }
        return map;
    }
}
